package cn.graydove.bot.service.impl;

import cn.graydove.bot.model.entity.Administrator;
import cn.graydove.bot.model.entity.Mock;
import cn.graydove.bot.model.entity.QqGroup;
import cn.graydove.bot.model.entity.User;
import cn.graydove.bot.repository.AdministratorRepository;
import cn.graydove.bot.repository.GroupRepository;
import cn.graydove.bot.repository.MockRepository;
import cn.graydove.bot.repository.UserRepository;
import cn.graydove.bot.service.GroupService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;
import java.util.Objects;

@Service
public class GroupServiceImpl implements GroupService {

    private AdministratorRepository administratorRepository;

    private GroupRepository groupRepository;

    private UserRepository userRepository;

    private MockRepository mockRepository;

    public GroupServiceImpl(AdministratorRepository administratorRepository, GroupRepository groupRepository, UserRepository userRepository, MockRepository mockRepository) {
        this.administratorRepository = administratorRepository;
        this.groupRepository = groupRepository;
        this.userRepository = userRepository;
        this.mockRepository = mockRepository;
    }

    @Override
    public List<QqGroup> findAll() {
        return groupRepository.findAll();
    }

    @Override
    public QqGroup findByGroupNumber(Long groupNumber) {
        return groupRepository.findByGroupNumber(groupNumber).orElse(null);
    }

    @Override
    @Transactional(rollbackFor = {RuntimeException.class})
    public void grant(QqGroup group, Long qqNumber) {
        Administrator administrator = new Administrator(qqNumber);
        administrator = administratorRepository.save(administrator);

        group.getAdministrator().add(administrator);

        groupRepository.save(group);
    }

    @Override
    @Transactional(rollbackFor = {RuntimeException.class})
    public void revoke(QqGroup group, Long qqNumber) {

        for (var a: group.getAdministrator()) {
            if (Objects.equals(a.getQqNumber(), qqNumber)) {
                group.getAdministrator().remove(a);
                groupRepository.save(group);
                administratorRepository.delete(a);
                return;
            }
        }

    }

    @Override
    @Transactional(rollbackFor = {RuntimeException.class})
    public QqGroup addUser(QqGroup group, User user) {
        user = userRepository.save(user);
        group.getUsers().add(user);
        return groupRepository.save(group);
    }

    @Override
    @Transactional(rollbackFor = {RuntimeException.class})
    public void addMock(QqGroup group, Mock mocks) {
        Mock mock = mockRepository.save(mocks);
        group.getMocks().add(mock);
        groupRepository.save(group);
    }

    @Override
    @Transactional(rollbackFor = {RuntimeException.class})
    public void removeMocks(QqGroup group, Collection<Mock> mocks) {
        if (mocks == null) {
            return;
        }
        group.getMocks().removeAll(mocks);
        groupRepository.save(group);

        mockRepository.deleteAll(mocks);
    }

    @Override
    @Transactional
    public void clearAttack() {
        userRepository.clearAllAttack();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ)
    public boolean isAttacking(Long groupId) {
        return groupRepository.isAttacking(groupId) != null;
    }

    @Override
    public boolean isOpen(Long groupId) {
        Boolean open = groupRepository.isOpen(groupId);
        return Boolean.TRUE.equals(open);
    }

    @Override
    public User saveUser(User uer) {
        return userRepository.save(uer);
    }

    @Override
    public QqGroup save(QqGroup group) {
        return groupRepository.save(group);
    }


}
